/**
 * @author Caius
 * @description 定义分表策略的配置类
 * @version 1.0
 * @since Created in 2025-02-24
 */
package com.itsense.stock.sharding;
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.joda.time.DateTime;

import java.util.Collection;
import java.util.Date;
import java.util.Optional;
import java.util.stream.Collectors;

public class CommonAlg4Tb implements PreciseShardingAlgorithm<Date>, RangeShardingAlgorithm<Date> {
    /**
     * 精准查询操作 cur_time的条件必须是=或者in
     * 按月分表
     * @param tbNames
     * @param shardingValue
     * @return
     */
    @Override
    public String doSharding(Collection<String> tbNames, PreciseShardingValue<Date> shardingValue) {
        //获取逻辑表
        String logicTableName = shardingValue.getLogicTableName();
        //获取分片键cur_time
        String columnName = shardingValue.getColumnName();
        //获取等值查询的条件值
        Date curTime = shardingValue.getValue();
        //获取当前时间的年份
        String yearMonth = new DateTime(curTime).toString("yyyyMM");
        Optional<String> result = tbNames.stream().filter(tbName -> tbName.endsWith(yearMonth)).findFirst();
        if (result.isPresent()) {
            return result.get();
        }
        return null;
    }

    /**
     * 实现范围查询分片操作
     * @param tbNames
     * @param shardingValue
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection<String> tbNames, RangeShardingValue<Date> shardingValue) {
        //获取逻辑表
        String logicTableName = shardingValue.getLogicTableName();
        //获取分片键cur_date
        String columnName = shardingValue.getColumnName();
        //获取范围信息
        Range<Date> valueRange = shardingValue.getValueRange();
        //判断下限
        if (valueRange.hasLowerBound()) {
            Date lowerDate = valueRange.lowerEndpoint();
            int startYearMonth = Integer.parseInt(new DateTime(lowerDate).toString("yyyyMM"));
            tbNames =  tbNames.stream().filter(tbName -> Integer.parseInt(tbName.substring(tbName.lastIndexOf("_")+1))>=startYearMonth).collect(Collectors.toList());
        }
        //判断上限
        if (valueRange.hasUpperBound()) {
            Date upperDate = valueRange.upperEndpoint();
            int endYearMonth = Integer.parseInt(new DateTime(upperDate).toString("yyyyMM"));
            tbNames =  tbNames.stream().filter(tbName -> Integer.parseInt(tbName.substring(tbName.lastIndexOf("-")+1))<=endYearMonth).collect(Collectors.toList());

        }
        return tbNames;
    }
}
